<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    /*
         写一个方法，该方法将传入的函数放进微队列中执行
         类似vue中nextTick

         node相关知识补充：
         process.nextTick()，效率最高，消费资源小，但会阻塞CPU的后续调用；
         setTimeout()，精确度不高，可能有延迟执行的情况发生，且因为动用了红黑树，所以消耗资源大；
         setImmediate()，消耗的资源小，也不会造成阻塞，但效率也是最低的。
         其中process.nextTick回调执行类似微任务，优先执行，再次是setTimeout,然后是setImmediate
         etTimeout采用的是类似IO观察者，setImmediate采用的是check观察者，而process.nextTick()采用的是idle观察者。
         三种观察者的优先级顺序是：idle观察者>>io观察者>check观察者

         还有一个window原生方法, Window 或 Worker 接口的 queueMicrotask() 方法，将微任务加入队列以在控制返回浏览器的事件循环之前的安全时间执行。
         这个方法目的主要是提供一种安全的调用方式，promise方式会带来额外开销等问题
         queueMicrotask(() => {
          微任务中将运行的代码 
        });
         微任务函数本身没有参数，也不返回值
        */

    function runMicroTask(fn) {

      // 如果存在Promises，优先用Promise
      if (typeof Promise === 'function') {
        Promise.resolve().then(fn)
        return
      }

      /*
       节点观察器，由于DOM 的任何变动，比如节点的增减、属性的变动、文本内容的变动都会触发MutationObserver事件。
       Mutation Observer 异步触发，会将回调放进微队列，因此我们可以利用这个特点手动触发文本内容更改触发
      */
      if (typeof MutationObserver === 'function') {
        let node = document.createTextNode('')
        const obseverDom = new MutationObserver(fn)
        // characterData监听文本内容变化
        obseverDom.observe(node, {
          characterData: true
        })
        node.data = 1
        return
      }

      // node环境
      if (process && typeof process.nextTick === 'function') {
        process.nextTick(fn)
        return
      }

      // node
      if (typeof setImmediate === 'function') {
        setImmediate(fn)
        return

      }

      // 都不支持再用setTImeOut
      setTimeout(fn, 0)

    }


    runMicroTask(() => {
      console.log('[ microTask ] >', '微任务执行了')
    })

    console.log('[ 1 ] >', 1)

    setTimeout(() => {
      console.log('[ 2 ] >', 2)
    }, 0)
  </script>

</body>

</html>